
package com.bdth.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bdth.model.FuncConfig;
import com.bdth.model.RoleFuncKey;
import com.bdth.model.User;
import com.bdth.service.IFuncConfigService;
import com.bdth.service.IRoleFuncService;
import com.bdth.service.IUserService;
import com.bdth.utils.JacksonUtils;
import com.bdth.utils.SessionUtils;
import com.bdth.utils.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

@Controller
public class MainController extends BaseController {


	@Autowired
	private IUserService userService;

	@Autowired
	private IFuncConfigService funcConfigService;


	@Autowired
	private IRoleFuncService roleFuncService;

	List<FuncConfig> authorizedFuncs = new ArrayList();

	@GetMapping("/login")
	public ModelAndView login(HttpServletRequest request,
	                          HttpServletResponse response) throws Exception {

		//获取Session
		User user = SessionUtils.getUser(request);
		String path = request.getContextPath();
		if (user != null) {
			return new ModelAndView("redirect:/main");
		}

		return forword("/login");
	}


	/**
	 * 登录
	 */
	@PostMapping("/toLogin")
	public void toLogin(String loginName, String passWord,
	                    HttpServletRequest request, HttpServletResponse response)
			throws Exception {

		User user = userService.queryLogin(loginName, passWord);

		if (user == null) {
			sendFailureMessage(response, "账号或者密码错误!");
			return;
		}
		//设置User到Session
		SessionUtils.setUser(request, user);
		sendSuccessMessage(response, "登录成功.");
	}


	/**
	 * 主页面
	 *
	 * @return
	 */
	@GetMapping(value = "/main")
	public ModelAndView getMainPage(HttpServletRequest request, HttpServletResponse response) throws Exception {
		User user1 = SessionUtils.getUser(request);
		if (user1 == null) {
			String path = request.getContextPath();
			response.sendRedirect(path + "/login");
			return null;
		}
		User user = userService.queryById(user1.getId());
		//设置User到Session
		SessionUtils.setUser(request, user);
		Map<String, Object> context = getRootMap();
		if (user != null) {
			context.put("user", user);
		}

		//获取权限菜单
		authorizedFuncs = new ArrayList<FuncConfig>();
		Map funcConfigMap = new HashMap<>();

		Map<String, Object> mapRoleFunc = new HashMap<String, Object>();
		if (user != null) {
			if (StringUtil.isEmptyWithNullStr("" + user.getRoleID())) {
				user.setRoleID(1);
			}
		}
		mapRoleFunc.put("roleId", user.getRoleID());
		List<RoleFuncKey> roleFuncList = roleFuncService.queryByMapList(mapRoleFunc);

		Map<String, Object> mapFunc = new HashMap<String, Object>();
		List<FuncConfig> allFuncList = funcConfigService.queryByMapList(mapFunc);

		for (FuncConfig fc : allFuncList) {
			funcConfigMap.put(fc.getId(), fc);
		}
		for (RoleFuncKey rf : roleFuncList) {
			authorizedFuncs.add((FuncConfig) funcConfigMap.get(rf.getFuncID()));
		}

		String path = request.getContextPath();
		// 根据用户分配的角色权限，得到系统顶部的主菜单，并生成菜单树在前台展现
		context.put("mainMenu", convertFuncsToMenu(path, authorizedFuncs, FuncConfig.FUNC_TYPE_MAIN_MENU));
		context.put("rightMenu", convertFuncsToMenu(path, authorizedFuncs, FuncConfig.FUNC_TYPE_RIGHT_MENU));
		context.put("userInfo", JacksonUtils.obj2json(user));
		return forword("/main/main", context);
	}


	/**
	 * 地图页面
	 *
	 * @return
	 */
	@GetMapping(value = "/map")
	public ModelAndView getMapPage(Model model) {

		return forword("/map/baidu");
	}

	/**
	 * 地图页面
	 *
	 * @return
	 */
	@GetMapping(value = "/google")
	public ModelAndView getGoogleMapPage(Model model) {

		return forword("/map/google");
	}

	/**
	 * 地图页面
	 *
	 * @return
	 */
	@GetMapping(value = "/leaflet")
	public ModelAndView getLeafletPage(Model model) {

		return forword("/map/leaflet");
	}


	/**
	 * 修改密码
	 *
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/updatePwd")
	public void updatePwd(String passWord, String newPassWord,
	                      HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		User user = SessionUtils.getUser(request);
		User bean = userService.queryById(user.getId());
		if (bean.getId() == null || 1 == bean.getDeleted().intValue()) {
			sendFailureMessage(response, "用户不存在");
			return;
		}
		if (StringUtil.isEmptyWithNullStr(newPassWord)) {
			sendFailureMessage(response, "请输入新密码");
			return;
		}
		//匹配旧密码
		if (!passWord.equals(bean.getPassWord())) {
			sendFailureMessage(response, "原始密码错误");
			return;
		}
		User u = new User();
		u.setId(user.getId());
		u.setPassWord(newPassWord);
		userService.updateBySelective(u);
		sendSuccessMessage(response, "保存成功~");
	}


	/**
	 * 退出登录
	 *
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	@GetMapping("/logout")
	public void logout(HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		String path = request.getContextPath();
		SessionUtils.removeUser(request);
		request.getSession().invalidate();//清除 session 中的所有信息
		response.sendRedirect(path + "/login");
	}


	/**
	 * 将用户分配的权限转换成主菜单的JSON数据，输出到前台
	 *
	 * @param authorizedFuncs 用户分配的功能权限
	 * @param funcType        主菜单
	 * @return
	 */
	private String convertFuncsToMenu(String path, List<FuncConfig> authorizedFuncs, Integer funcType) throws Exception {


		Map<String, Object> mapFunc = new HashMap<String, Object>();
		mapFunc.put("parentID", 0);
		mapFunc.put("funcType", funcType);
		List<FuncConfig> subSysFuncs = funcConfigService.queryByMapList(mapFunc);
		JSONArray jsonArray = new JSONArray();
		for (FuncConfig func : subSysFuncs) {
			List<FuncConfig> childSysFuns = findChidFuncByParentId(
					func.getId(), authorizedFuncs);
			JSONObject menuItem = new JSONObject();
			menuItem.put("id", "" + func.getId());
			menuItem.put("text", func.getFuncName());
			menuItem.put("url", func.getUrl());
			menuItem.put("icon", func.getIconCls());
			menuItem.put("funcName", func.getName());
			JSONObject attributes = new JSONObject();
			attributes.put("url", func.getUrl());
			menuItem.put("attributes", attributes);

			JSONArray childMenuItems = new JSONArray();
			for (FuncConfig childSysFunc : childSysFuns) {
				JSONObject childItem = new JSONObject();
				childItem.put("id", "" + childSysFunc.getId());
				childItem.put("text", childSysFunc.getFuncName());
				childItem.put("funcName", childSysFunc.getName());
				childItem.put("icon", childSysFunc.getIconCls());
				String url = "";
				if (!StringUtil.isEmpty(childSysFunc.getUrl())) {
					url = path + "/" + childSysFunc.getUrl();
				}

				attributes = new JSONObject();

				childItem.put("url", url);
				childItem.put("attributes", attributes);
				childMenuItems.add(childItem);
			}
			if (childMenuItems.size() > 0) {
				menuItem.put("items", childMenuItems);
				jsonArray.add(menuItem); //如果父菜单下没有子菜单，就不显示在前台
			} else if (isAuthorized(func)) {
				jsonArray.add(menuItem);
			}

		}

		return jsonArray.toString();
	}

	private boolean isAuthorized(FuncConfig f) {
		for (FuncConfig fn : authorizedFuncs) {
			if (f.getId() == fn.getId() && fn.getDeleted().intValue() == 0) {
				return true;
			}
		}
		return false;
	}

	private List<FuncConfig> findChidFuncByParentId(Integer parentId,
	                                                List<FuncConfig> authorizedFuncs) {
		List subSysFuncs = new ArrayList();
		for (FuncConfig sysFunc : authorizedFuncs) {
			if (sysFunc.getParentID().intValue() == parentId.intValue()
					&& sysFunc.getDeleted().intValue() == 0) {
				subSysFuncs.add(sysFunc);
			}
		}

		Collections.sort(authorizedFuncs, new SysFuncComparator());
		return subSysFuncs;
	}


	class SysFuncComparator implements Comparator<FuncConfig> {
		SysFuncComparator() {
		}

		public int compare(FuncConfig paramT1, FuncConfig paramT2) {
			int sort1 = paramT1.getSort() == null ? 0 : paramT1
					.getSort().intValue();

			int sort2 = paramT2.getSort() == null ? 0 : paramT2
					.getSort().intValue();

			return sort1 - sort2;
		}
	}

}
